package com.pangda.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import com.pangda.common.constant.HttpStatusConstant;
import com.pangda.common.constant.MenuTypeConstant;
import com.pangda.common.domain.ResponseResult;
import com.pangda.common.utils.UserContext;
import com.pangda.pojo.SysMenu;
import com.pangda.mapper.SysMenuMapper;
import com.pangda.pojo.SysRoleMenu;
import com.pangda.pojo.dto.SysMenuDto;
import com.pangda.pojo.vo.MenuTreeVo;
import com.pangda.pojo.vo.NodeVo;
import com.pangda.service.ISysMenuService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pangda.service.ISysRoleMenuService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 菜单权限表 服务实现类
 * </p>
 *
 * @author xjy
 * @since 2024-06-20
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements ISysMenuService {

    @Autowired
    private ISysRoleMenuService sysRoleMenuService;

    /**
     * 新增菜单
     *
     * @param sysMenuDto 菜单信息
     */
    @Override
    public ResponseResult add(SysMenuDto sysMenuDto) {
        SysMenu byId = getById(sysMenuDto.getParentId());
        if (ObjectUtil.isEmpty(byId) || MenuTypeConstant.BUTTON.equals(byId.getMenuType())) {
            return ResponseResult.error("按钮类型不能作为父级菜单");
        }
        Integer level = countLevel(sysMenuDto);
        if (level > 3 && MenuTypeConstant.MENU.equals(sysMenuDto.getMenuType())) {
            return ResponseResult.error("菜单层级不能超过四级");
        }
        SysMenu sysMenu = BeanUtil.toBean(sysMenuDto, SysMenu.class);
        sysMenu.setCreateBy(UserContext.getUser());
        sysMenu.setCreateTime(LocalDateTime.now());
        sysMenu.setUpdateTime(LocalDateTime.now());
        save(sysMenu);
        return ResponseResult.success();
    }

    /**
     * 删除菜单
     *
     * @param menuId 菜单id
     * @return 是否删除成功
     */
    @Override
    public ResponseResult deleteMenu(Long menuId) {
        SysMenu sysMenu = getById(menuId);
        if (ObjectUtil.isEmpty(sysMenu)) {
            return ResponseResult.error("菜单不存在");
        }
        LambdaQueryWrapper<SysMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysMenu::getParentId, menuId);
        List<SysMenu> list = list(queryWrapper);
        if (ObjectUtil.isNotEmpty(list)) {
            return ResponseResult.error("菜单下存在子菜单，不能删除");
        }
        removeById(menuId);
        return ResponseResult.success();
    }

    /**
     * 获取菜单树
     *
     * @return 菜单树
     */
    @Override
    public ResponseResult<NodeVo> treeSelect() {
        List<SysMenu> list = list();
        List<NodeVo> nodeVos = getNodeVos(list);
        return ResponseResult.success(nodeVos);
    }

    // 获取菜单树
    private List<NodeVo> getNodeVos(List<SysMenu> nodeVos) {
        if (ObjectUtil.isEmpty(nodeVos)) {
            return Collections.emptyList();
        }

        List<NodeVo> nodeVoList = nodeVos.stream().map(sysMenu -> {
            NodeVo nodeVo = new NodeVo();
            nodeVo.setLabel(sysMenu.getMenuName());
            nodeVo.setId(Math.toIntExact(sysMenu.getMenuId()));
            nodeVo.setParentId(Math.toIntExact(sysMenu.getParentId()));
            return nodeVo;
        }).collect(Collectors.toList());

        //创建一个Map，父id为键，值是节点
        Map<Integer, NodeVo> collect = nodeVoList.stream().collect(Collectors.toMap(NodeVo::getId, nodeVo -> nodeVo, (k1, k2) -> k1));

        //创建一个集合，用于存储根节点
        List<NodeVo> treeList = new ArrayList<>();
        Map<Integer, NodeVo> nodeMap = new HashMap<>();


        // 第一次遍历，将所有节点包括根节点和子节点放入nodeMap
        for (NodeVo nodeVo : nodeVoList) {
            nodeMap.put(nodeVo.getId(), nodeVo);
            // 如果是根节点，则直接加入treeList
            if (nodeVo.getParentId() == 0) {
                treeList.add(nodeVo);
            }
        }

        for (NodeVo nodeVo : nodeVoList) {
            Integer parentId = nodeVo.getParentId();
            if (parentId != 0) {
                NodeVo parentNode = nodeMap.get(parentId);
                if (parentNode != null) {
                    parentNode.addChild(nodeVo);
                }
            }
        }
        return treeList;
    }


    //递归查询子菜单节点
    private void getAllChildIds(Long parentId, List<SysMenu> menus, List<Integer> childIds) {
        for (SysMenu sysMenu : menus) {
            if (sysMenu.getParentId().equals(parentId)) {
                childIds.add(Math.toIntExact(sysMenu.getMenuId()));
                getAllChildIds(sysMenu.getMenuId(), menus, childIds);
            }
        }
    }

    /**
     * 获取角色菜单树
     *
     * @param roleId 角色id
     * @return
     */
    @Override
    public MenuTreeVo roleMenuTreeSelect(Long roleId) {
        List<SysMenu> list = list();
        List<NodeVo> nodeVos = getNodeVos(list);
        LambdaQueryWrapper<SysRoleMenu> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ObjectUtil.isNotEmpty(roleId), SysRoleMenu::getRoleId, roleId);
        List<SysRoleMenu> list1 = sysRoleMenuService.list(queryWrapper);
        List<Integer> collect = list1.stream().map(sysRoleMenu -> sysRoleMenu.getMenuId()).collect(Collectors.toList());
        return MenuTreeVo.success("查询成功", nodeVos, collect);
    }

    /**
     * 获取菜单层级
     *
     * @param sysMenuDto 菜单信息
     * @return 菜单层级
     */
    public Integer countLevel(SysMenuDto sysMenuDto) {
        int count = 0;
        SysMenu byId = getById(sysMenuDto.getParentId());
        while (ObjectUtil.isNotEmpty(byId)) {
            count++;
            byId = getById(byId.getParentId());
        }
        return count;
    }
}
